#!/usr/bin/python2.5
"""Fetches the SA CFS incident data webpage, turns into RSS feed."""

import datetime
import StringIO
from xml.dom import minidom
import BeautifulSoup
from controllers import geocode
from controllers import query
from google.appengine.api import urlfetch
from google.appengine.ext import webapp
import wsgiref.handlers


def GenRSS(incidents):
  """Turns a list of incident dictionaries into an RSS feed."""
  impl = minidom.getDOMImplementation()
  doc = impl.createDocument(None, 'rss', None)
  rss = doc.childNodes[0]
  rss.setAttribute('xmlns:georss', 'http://www.georss.org/georss')
  rss.setAttribute('xmlns:atom', 'http://www.w3.org/2005/Atom')
  rss.setAttribute('version', '2.0')
  rss.setAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/')
  rss.setAttribute('xmlns:rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#')
  rss.setAttribute('xmlns:taxo', 'http://purl.org/rss/1.0/modules/taxonomy/')
  channel = rss.appendChild(doc.createElement('channel'))
  channel.appendChild(doc.createElement('title')).appendChild(
      doc.createTextNode('SA CFS Fire Information'))
  description = channel.appendChild(doc.createElement('description'))
  description.appendChild(doc.createTextNode(
      'This is an RSS view of the data from the page '
      'http://www.cfs.sa.gov.au/site/news_media/current_incidents.jsp'))
  for incident in incidents:
    if incident['status'] == 'COMPLETE': continue
    item = channel.appendChild(doc.createElement('item'))
    item.appendChild(doc.createElement('title')
                    ).appendChild(
                        doc.createTextNode(incident['location name']))
    incident['datetime'] = datetime.datetime.strptime(
        '%s %s' % (incident['date'], incident['time']),
        '%d/%m/%Y %H:%M').strftime('%a, %d %b %Y %H:%M:%S')

    item.appendChild(doc.createElement('pubDate')
                    ).appendChild(doc.createTextNode(incident['datetime']))
    if 'type' not in incident:
      incident['type'] = 'Unknown'
    incident['ourlevel'] = {
        '1': 'SMALL',
        '2': 'MEDIUM',
        '3': 'LARGE'}.get(incident['level'], '')
    desc = ('Location: %(location name)s<br/>Type: %(type)s<br/>'
            'Date: %(datetime)s<br/>'
            'Status: %(status)s<br/>Region: %(region)s<br/>'
            'Level: %(level)s %(ourlevel)s<br/><br/>'
            'Information from SA Country Fire Service. See '
            'http://www.cfs.sa.gov.au for more.'%(incident))
    item.appendChild(doc.createElement('description')
                    ).appendChild(doc.createCDATASection(desc.encode('utf-8')))
    if incident['lat']:
      point = item.appendChild(doc.createElement('georss:point'))
      point.appendChild(
          doc.createTextNode('%s %s' % (incident['lat'], incident['long'])))
    item.appendChild(doc.createElement('georss:featuretypetag')
                    ).appendChild(doc.createTextNode('area'))
  output_rss = StringIO.StringIO()
  doc.writexml(output_rss)
  return output_rss.getvalue()


class FetchRSS(webapp.RequestHandler):
  """Fetch the CFS webpage, munge into RSS, store the RSS."""

  def get(self):
    """GET handler."""
    result = urlfetch.fetch(
        'http://www.cfs.sa.gov.au/site/news_media/current_incidents.jsp')
    if result.status_code == 200:
      incidents = MungeSaCfsHtml(result.content)
      rss = GenRSS(incidents).encode('utf-8')
      query.PutData('sacfs', rss)

      self.response.headers.add_header('Cache-control',
                                       'no-cache, must-revalidate')
      self.response.headers['Content-Type'] = 'text/plain'
      self.response.out.write(rss)


def MungeSaCfsHtml(html):
  """Turns the SA CFS HTML into a list of dictionaries, one per incident."""
  bs = BeautifulSoup.BeautifulSoup(html)
  table = bs.find('table', attrs={'id': 'TableList'})
  keys = []
  incidents = []
  for tr in table.findAll('tr'):
    if tr.find('th'):
      for th in tr.findAll('th'):
        keys.append(th.contents[0].lower())
    else:
      incident = {}
      incidents.append(incident)
      for key, td in zip(keys, tr.findAll('td')):
        if td.contents:
          incident[key] = td.contents[0]
      lat, longt, _ = geocode.GetLocation(incident['location name'],
                                          state='south australia')
      incident['lat'] = lat
      incident['long'] = longt
      incident['approx'] = True
  return incidents


def main():
  app = webapp.WSGIApplication([
      ('/query/sacfs', FetchRSS),
      ], debug=True)
  wsgiref.handlers.CGIHandler().run(app)

if __name__ == '__main__':
  main()
